/*
 * Created: Author: Aléx Carvalho / Date: Jun 3, 2015
 * 
 * Changed: $Author: ac280593@gmail.com $ / $Date: 2015-06-11 04:28:43 +0000 (Thu, 11 Jun 2015) $
 */
package test;

import com.cpm.entities.Identity;
import com.cpm.entities.id.Id;
import com.cpm.repository.GenericRepository;
import com.cpm.wrapper.exception.SystemException;
import com.uaihebert.uaicriteria.UaiCriteria;
import com.uaihebert.uaicriteria.UaiCriteriaFactory;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.List;
import javax.ejb.Stateful;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceContextType;

@Stateful
public class SystemDAOStateful <IDENTITY extends Identity> implements GenericRepository<IDENTITY> {
    @PersistenceContext( type=PersistenceContextType.EXTENDED)
    private EntityManager entityManager;
    
    private final Class<IDENTITY> entityClass;

    public SystemDAOStateful() {
        this.entityClass = getEntityClass();
    }

    public void persist(IDENTITY value) {
        prePersist(value);

        entityManager.persist(value);

        postPersist(value);
    }

    public void persistList(Collection<IDENTITY> values) {
        values.forEach(value -> {
            prePersist(value);
            entityManager.persist(value);
            postPersist(value);
        });

    }

    public void update(IDENTITY value) {
        preUpdate(value);

        entityManager.merge(value);

        postUpdate(value);
    }

    public IDENTITY findById(Id id) {
        IDENTITY identity = entityManager.find(entityClass, id.getId());

        postLoad((IDENTITY) identity);

        return (IDENTITY) identity;
    }

    public Collection<IDENTITY> findAll() {
        UaiCriteria<IDENTITY> criteria = UaiCriteriaFactory.createQueryCriteria(entityManager, entityClass);
        List<IDENTITY> values = criteria.getResultList();

        postLoadList(values);
        return values;
    }

    public void prePersist(IDENTITY value) {
        System.out.println("prePersist");
    }

    public void preUpdate(IDENTITY value) {
        System.out.println("preUpdate");
    }

    public void postLoad(IDENTITY value) {
        System.out.println("postLoad");
    }

    public void postLoadList(List<IDENTITY> values) {
        System.out.println("postLoad");
    }

    public void postPersist(IDENTITY value) {
        System.out.println("postPersist");
    }

    public void postUpdate(IDENTITY value) {
        System.out.println("postUpdate");
    }

    private Class<IDENTITY> getEntityClass() {
        Type type = getClass().getGenericSuperclass();

        if (type instanceof Class) {
            type = ((Class) type).getGenericSuperclass();
        }

        if (type instanceof ParameterizedType) {
            ParameterizedType parameterizedType = (ParameterizedType) type;

            return (Class<IDENTITY>) parameterizedType.getActualTypeArguments()[0];
        }

        throw new SystemException("Not possible obtain instance for entityClass!");
    }
}
